﻿using System;
using System.Linq;
using System.ServiceModel;

using System.Text.Json;
using System.Threading.Tasks;
using HengTong.DataAccess;
using HengTong.Kingdee.Connected_Services.WSExportMaterialFacadeSrvProxyService;
using HengTong.Kingdee.Connected_Services.WSExportMaterialGroupFacade;
using HengTong.Kingdee.Eas;
using HengTong.Kingdee.EASLoginProxyService;
using HengTong.Kingdee.WSExportMaterialFacadeSrvProxyService;
using HengTong.Kingdee.WSExportMaterialGroupFacadeSrvProxyService;
using HengTong.Kingdee.WSWMSImportBillFacadeSrvProxyService;
using HengTong.Model.Interfaces;
using HengTong.Model.Services;
using HengTong.Services;
using HengTong.ViewModel.Person.SysPersonRepairBillVms;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Serilog;
using Serilog.Core;
using TiaoTaoHelper.Wtm.Extension;
using TiaoTaoHelper.Wtm.Models;
using TiaoTaoHelper.Wtm.Workflow;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Support.FileHandlers;

namespace HengTong.Test;

[TestClass]
public class TestTask
{
    private ServiceProvider _serviceProvider;

    [TestInitialize]
    public void TestInitialize()
    {
        var config = InitConfiguration();
        
        // 配置 Serilog
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .CreateLogger();
        var services = new ServiceCollection();
        services.AddLogging(builder => { builder.AddSerilog(dispose: true); });
        services.AddMemoryCache();
        services.AddSingleton(config);
        services.AddScoped<WtmFileProvider>();
        services.Configure<Configs>(config);
        config.Get<Configs>();
        services.AddScoped<Logger>();
        services.AddScoped<AwsTaskService>();
        services.AddScoped<CodeGeneratorService>();
        services.AddScoped<XenWorkflowService>();
        services.AddXenWorkflow(config);
        // 注册 DataContext 作为 IDataContext
        var dataContext = new DataContext(
            "Server=42.225.116.55,19926;Database=HengTongTest;user id=sa;password=Jia123wei!;TrustServerCertificate=True",
            DBTypeEnum.SqlServer);
        services.AddSingleton<IDataContext>(dataContext);
        services.AddScoped<DataSyncService>();
        services.AddScoped<EasDataProvider>();
        services.AddEasService(config);
        // 构建 ServiceProvider
        _serviceProvider = services.BuildServiceProvider();
        
        var wtm = MockWtmContext.CreateWtmContext(dataContext, "admin");
        
        services.AddSingleton(wtm);
        
        // 重新构建 ServiceProvider 以包含 wtm
        _serviceProvider = services.BuildServiceProvider();
        
        // 重新设置 ServiceProvider，确保 wtm 使用正确的服务提供者
        wtm.SetServiceProvider(_serviceProvider);
    }

    private IConfiguration InitConfiguration()
    {
        var config = new ConfigurationBuilder()
            .AddJsonFile("appsettings.development.json")
            .Build();
        return config;
    }

    [TestMethod]
    public async Task TestCreateProcess()
    {
        var scope = _serviceProvider.CreateScope();
        var service = scope.ServiceProvider.GetRequiredService<AwsTaskService>();

        //----------首先创建一个流程实例
        Console.WriteLine("----------首先创建一个流程实例");
        var createResult = await service.CreateProcessAsync("obj_155af7bc89db4912952e3eef5c638437", "admin", "测试流程",
            null, null, null, null);
        Assert.IsTrue(createResult.Code == 200, createResult.Message);
        Console.WriteLine(createResult.Message);

        // 将对象转换为JSON字符串，然后解析提取所需字段，解析返回的流程实例ID
        var createJsonString = System.Text.Json.JsonSerializer.Serialize(createResult.Data);
        var createJsonElement = System.Text.Json.JsonDocument.Parse(createJsonString).RootElement;
        string processInstId = createJsonElement.GetProperty("id").GetString();
        string processDefId = createJsonElement.GetProperty("processDefId").GetString();

        Console.WriteLine($"流程实例ID: {processInstId}");
        Console.WriteLine($"流程定义ID: {processDefId}");


        //----------启动流程
        Console.WriteLine("----------启动流程");
        var startResult = await service.StartProcessAsync(processInstId);
        Assert.IsTrue(startResult.Code == 200, startResult.Message);
        Console.WriteLine(startResult.Message);
        //Console.WriteLine("流程启动结果: " + System.Text.Json.JsonSerializer.Serialize(startResult.Data));

        var startJsonString = System.Text.Json.JsonSerializer.Serialize(startResult.Data);
        var startJsonElement = System.Text.Json.JsonDocument.Parse(startJsonString).RootElement;
        string taskInstId = startJsonElement.GetProperty("activeTasks")[0].GetProperty("id").GetString();
        Console.WriteLine($"任务实例ID: {taskInstId}");

        //----------获取流程实例信息
        Console.WriteLine("----------获取流程实例信息");
        var getProcessResult = await service.GetProcessAsync(processInstId);
        Assert.IsTrue(getProcessResult.Code == 200, getProcessResult.Message);
        Console.WriteLine(getProcessResult.Message);
        //Console.WriteLine("流程实例信息: " + System.Text.Json.JsonSerializer.Serialize(getProcessResult.Data));
        var getProcessJsonString = System.Text.Json.JsonSerializer.Serialize(getProcessResult.Data);
        var getProcessJsonElement = System.Text.Json.JsonDocument.Parse(getProcessJsonString).RootElement;
        string startTaskInstId = getProcessJsonElement.GetProperty("startTaskInstId").GetString();
        Console.WriteLine($"流程启动任务实例ID: {startTaskInstId}");


        //----------完成第一个节点任务
        Console.WriteLine("----------完成第一个节点任务");
        var completeTaskResult = await service.CompleteTaskAsync(startTaskInstId, "admin");
        Assert.IsTrue(completeTaskResult.Code == 200, completeTaskResult.Message);
        Console.WriteLine(completeTaskResult.Message);
        //Console.WriteLine("完成任务结果: " + System.Text.Json.JsonSerializer.Serialize(completeTaskResult.Data));
        var completeTaskJsonString = System.Text.Json.JsonSerializer.Serialize(completeTaskResult.Data);
        var completeTaskJsonElement = System.Text.Json.JsonDocument.Parse(completeTaskJsonString).RootElement;
        // 判断流程是否结束以及是否有下一个活动任务
        bool isProcessEnd = completeTaskJsonElement.TryGetProperty("isProcessEnd", out var isEndElement) &&
                            isEndElement.GetBoolean();
        Console.WriteLine($"流程是否结束: {isProcessEnd}");
        if (isProcessEnd)
        {
            Console.WriteLine("流程已结束，没有下一个活动任务。");
            return;
        }

        string taskId = completeTaskJsonElement.GetProperty("activeTasks")[0].GetProperty("id").GetString();
        Console.WriteLine($"下个节点: {taskId}");

        //----------判断当前任务是否结束
        Console.WriteLine("----------判断当前任务是否结束");
        var checkTaskCloseResult = await service.CheckTaskCloseAsync(startTaskInstId);
        Assert.IsTrue(checkTaskCloseResult.Code == 200, checkTaskCloseResult.Message);
        Console.WriteLine(checkTaskCloseResult.Message);
        Console.WriteLine($"当前任务是否结束: {checkTaskCloseResult.Data}");

        //----------判断整个流程是否结束
        Console.WriteLine("----------判断整个流程是否结束");
        var checkProcessEndResult = await service.CheckProcessEndAsync(processInstId);
        Assert.IsTrue(checkProcessEndResult.Code == 200, checkProcessEndResult.Message);
        Console.WriteLine(checkProcessEndResult.Message);
        Console.WriteLine($"整个流程是否结束: {checkProcessEndResult.Data}");


        //----------完成第二个节点任务
        Console.WriteLine("----------完成第二个节点任务");
        var completeTaskResult2 = await service.CompleteTaskAsync(taskId, "4151");
        Assert.IsTrue(completeTaskResult2.Code == 200, completeTaskResult2.Message);
        Console.WriteLine(completeTaskResult2.Message);
        //Console.WriteLine("完成任务结果: " + System.Text.Json.JsonSerializer.Serialize(completeTaskResult.Data));
        var completeTaskJsonString2 = System.Text.Json.JsonSerializer.Serialize(completeTaskResult2.Data);
        var completeTaskJsonElement2 =
            System.Text.Json.JsonDocument.Parse(completeTaskJsonString2).RootElement; // 判断流程是否结束以及是否有下一个活动任务
        bool isProcessEnd2 = completeTaskJsonElement2.TryGetProperty("isProcessEnd", out var isEndElement2) &&
                             isEndElement2.GetBoolean();
        Console.WriteLine($"流程是否结束: {isProcessEnd2}");
        if (isProcessEnd2)
        {
            Console.WriteLine("流程已结束，没有下一个活动任务。");
            return;
        }

        string taskId2 = completeTaskJsonElement2.GetProperty("activeTasks")[0].GetProperty("id").GetString();
        Console.WriteLine($"下个节点: {taskId2}");

        //----------判断当前任务是否结束
        Console.WriteLine("----------判断当前任务是否结束");
        var checkTaskCloseResult2 = await service.CheckTaskCloseAsync(taskId);
        Assert.IsTrue(checkTaskCloseResult2.Code == 200, checkTaskCloseResult2.Message);
        Console.WriteLine(checkTaskCloseResult2.Message);
        Console.WriteLine($"当前任务是否结束: {checkTaskCloseResult2.Data}");

        //----------判断整个流程是否结束
        Console.WriteLine("----------判断整个流程是否结束");
        var checkProcessEndResult2 = await service.CheckProcessEndAsync(processInstId);
        Assert.IsTrue(checkProcessEndResult2.Code == 200, checkProcessEndResult2.Message);
        Console.WriteLine(checkProcessEndResult2.Message);
        Console.WriteLine($"整个流程是否结束: {checkProcessEndResult2.Data}");

        //----------从当前节点回滚到上个节点
        Console.WriteLine("----------执行任务回滚");
        var rollbackResult =
            await service.RollbackTaskAsync(taskId2, "obj_92baecd106964e64969ad725ed7950e8", "admin", true, "测试回滚功能");
        Assert.IsTrue(rollbackResult.Code == 200, rollbackResult.Message);
        Console.WriteLine(rollbackResult.Message);
        //----------判断回滚结果数据
        var rollbackJsonString = System.Text.Json.JsonSerializer.Serialize(rollbackResult.Data);
        string rollbackTaskId = null;
        if (!string.IsNullOrEmpty(rollbackJsonString))
        {
            var rollbackJsonElement = System.Text.Json.JsonDocument.Parse(rollbackJsonString).RootElement;
            rollbackTaskId = rollbackJsonElement.GetProperty("id").GetString();
        }

        Console.WriteLine($"回滚后的节点: {rollbackTaskId}");

        //----------完成第二个节点任务
        Console.WriteLine("----------完成第二个节点任务");
        var completeTaskResult22 = await service.CompleteTaskAsync(rollbackTaskId, "admin");
        Assert.IsTrue(completeTaskResult22.Code == 200, completeTaskResult22.Message);
        Console.WriteLine(completeTaskResult22.Message);
        //Console.WriteLine("完成任务结果: " + System.Text.Json.JsonSerializer.Serialize(completeTaskResult.Data));
        var completeTaskJsonString22 = System.Text.Json.JsonSerializer.Serialize(completeTaskResult22.Data);
        var completeTaskJsonElement22 =
            System.Text.Json.JsonDocument.Parse(completeTaskJsonString22).RootElement; // 判断流程是否结束以及是否有下一个活动任务
        bool isProcessEnd22 = completeTaskJsonElement22.TryGetProperty("isProcessEnd", out var isEndElement22) &&
                              isEndElement22.GetBoolean();
        Console.WriteLine($"流程是否结束: {isProcessEnd22}");
        if (isProcessEnd22)
        {
            Console.WriteLine("流程已结束，没有下一个活动任务。");
            return;
        }

        string taskId22 = completeTaskJsonElement22.GetProperty("activeTasks")[0].GetProperty("id").GetString();
        Console.WriteLine($"下个节点: {taskId22}");


        //----------完成第三个节点任务
        Console.WriteLine("----------完成第三个节点任务");
        var completeTaskResult3 = await service.CompleteTaskAsync(taskId22, "admin");
        Assert.IsTrue(completeTaskResult3.Code == 200, completeTaskResult3.Message);
        Console.WriteLine(completeTaskResult3.Message);
        var completeTaskJsonString3 = System.Text.Json.JsonSerializer.Serialize(completeTaskResult3.Data);
        var completeTaskJsonElement3 = System.Text.Json.JsonDocument.Parse(completeTaskJsonString3).RootElement;
        // 判断流程是否结束以及是否有下一个活动任务
        bool isProcessEnd3 = completeTaskJsonElement3.TryGetProperty("isProcessEnd", out var isEndElement3) &&
                             isEndElement3.GetBoolean();
        Console.WriteLine($"流程是否结束: {isProcessEnd3}");
        if (isProcessEnd3)
        {
            Console.WriteLine("流程已结束，没有下一个活动任务。");
            return;
        }

        string taskId3 = completeTaskJsonElement3.GetProperty("activeTasks")[0].GetProperty("id").GetString();
        Console.WriteLine($"下个节点: {taskId3}");

        //----------判断当前任务是否结束
        Console.WriteLine("----------判断当前任务是否结束");
        var checkTaskCloseResult3 = await service.CheckTaskCloseAsync(taskId2);
        Assert.IsTrue(checkTaskCloseResult3.Code == 200, checkTaskCloseResult3.Message);
        Console.WriteLine(checkTaskCloseResult3.Message);
        Console.WriteLine($"当前任务是否结束: {checkTaskCloseResult3.Data}");

        //----------判断整个流程是否结束
        Console.WriteLine("----------判断整个流程是否结束");
        var checkProcessEndResult3 = await service.CheckProcessEndAsync(processInstId);
        Assert.IsTrue(checkProcessEndResult3.Code == 200, checkProcessEndResult3.Message);
        Console.WriteLine(checkProcessEndResult3.Message);
        Console.WriteLine($"整个流程是否结束: {checkProcessEndResult3.Data}");

        //----------完成第四个节点任务
        Console.WriteLine("----------完成第四个节点任务");
        var completeTaskResult4 = await service.CompleteTaskAsync(taskId3, "admin");
        Assert.IsTrue(completeTaskResult4.Code == 200, completeTaskResult4.Message);
        Console.WriteLine(completeTaskResult4.Message);
        var completeTaskJsonString4 = System.Text.Json.JsonSerializer.Serialize(completeTaskResult4.Data);
        var completeTaskJsonElement4 = System.Text.Json.JsonDocument.Parse(completeTaskJsonString4).RootElement;
        // 判断流程是否结束以及是否有下一个活动任务
        bool isProcessEnd4 = completeTaskJsonElement4.TryGetProperty("isProcessEnd", out var isEndElement4) &&
                             isEndElement4.GetBoolean();
        Console.WriteLine($"流程是否结束: {isProcessEnd4}");
        if (isProcessEnd4)
        {
            Console.WriteLine("流程已结束，没有下一个活动任务。");
            return;
        }
    }
    
    [TestMethod]
    public async Task TestCreateProcessWithCodeGenerator()
    {
        var scope = _serviceProvider.CreateScope();
        var wtm = scope.ServiceProvider.GetRequiredService<WTMContext>();
        var vm = wtm.CreateVM<SysPersonRepairBillVm>();
        var result = await vm.PredictCodeAsync();
        Assert.IsTrue(result.Code == 200, result.Message);
    }

    /// <summary>
    /// 测试路径计算
    /// </summary>
    [TestMethod]
    public async Task TestWorkflowPath()
    {
        var scope = _serviceProvider.CreateScope();
        var wtm = scope.ServiceProvider.GetRequiredService<WTMContext>();
        var groups = await wtm.DC.Set<SysGroup>()
            .Where(e => e.IsDisabled != true)
            .ToListAsync();
        var start = groups.FirstOrDefault(e => e.GroupName == "待岗中心");
        var target = groups.FirstOrDefault(e => e.GroupName == "一工段");
        if (target == null || start == null)
        {
            Console.WriteLine("未找到指定的审批组");
            return;
        }
        var path = wtm.FindWorkflowApprovalPath(start.ID, target.ID);
        if (path != null)
        {
            Console.WriteLine($"审批路径: {string.Join(" -> ", path.Select(e => e.GroupName))}");
        }
        else
        {
            Console.WriteLine("未找到审批路径");
        }
    }
    
    /// <summary>
    /// EAS登录
    /// </summary>
    [TestMethod]
    private async Task<string> EasLogin()
    {
        var client = EASLoginProxyClient.CreateFromConfiguration();
#if DEBUG
        var result = await client.loginAsync("ccpt", "ccpt123.", "eas", "cs02", "12", 2);
#else
        var result = await client.loginAsync("ccpt", "ccpt123.", "eas", "HT002", "12", 2);
#endif
        return result?.loginReturn?.sessionId;
    }
    
    /// <summary>
    /// EAS登录
    /// </summary>
    [TestMethod]
    public async Task EasWebServiceLogin()
    {
        var sessionId = await this.EasLogin();
        Assert.IsTrue(!string.IsNullOrWhiteSpace(sessionId), "登录失败");
        Console.WriteLine(sessionId);
    }
    
    /// <summary>
    /// EAS物料分组
    /// </summary>
    [TestMethod]
    public async Task EasWebServiceGroupData()
    {
        //登录获取 sessionId
        var sessionId = await this.EasLogin();
        Assert.IsTrue(!string.IsNullOrWhiteSpace(sessionId), "登录失败");
        //查询物料分组数据
        var client = WSExportMaterialGroupFacadeSrvProxyClient.CreateFromConfiguration();
        //必须初始化 scope, 否则无法添加 header 会抛出对象为空的异常
        _ = new OperationContextScope(client.InnerChannel);
        OperationContext.Current.OutgoingMessageHeaders.Add(new EasMessageHeader(sessionId));
        var result = await client.exportMaterialGroupDataAsync(0, 100);
        var data = result.ToMaterialGroupDataList();
        Console.WriteLine($"数据:{data.Count}");
    }


    /// <summary>
    /// EAS物料
    /// </summary>
    [TestMethod]
    public async Task EasWebServiceMaterialData()
    {
        //登录获取 sessionId
        var sessionId = await this.EasLogin();
        Assert.IsTrue(!string.IsNullOrWhiteSpace(sessionId), "登录失败");
        //查询物料
        var client = WSExportMaterialFacadeSrvProxyClient.CreateFromConfiguration();
        //必须初始化 scope, 否则无法添加 header 会抛出对象为空的异常
        _ = new OperationContextScope(client.InnerChannel);
        OperationContext.Current.OutgoingMessageHeaders.Add(new EasMessageHeader(sessionId));
        var result = await client.exportMatetialDataAsync(0, 3);
        var data = result.ToMaterialDataList();
        Console.WriteLine($"数据:{data.Count}");
    }

    /// <summary>
    /// 通用数据导出
    /// </summary>
    [TestMethod]
    public async Task EasCommonExport()
    {
        //登录获取 sessionId
        var sessionId = await this.EasLogin();
        Assert.IsTrue(!string.IsNullOrWhiteSpace(sessionId), "登录失败");
        //查询数据
        var client = WSWMSImportBillFacadeSrvProxyClient.CreateFromConfiguration();
        //必须初始化 scope, 否则无法添加 header 会抛出对象为空的异常
        _ = new OperationContextScope(client.InnerChannel);
        OperationContext.Current.OutgoingMessageHeaders.Add(new EasMessageHeader(sessionId));
        // 计量单位
        // var result = await client.exportDataAsync("5B825C57", 1, 10);
        // var data = result.ToMeasureUnitDataList();
        // Console.WriteLine($"数据长度:{data.Count}");
        
        // // 计量单位分组
        // var result = await client.exportDataAsync("1C2AC868", 1, 10);
        // var data = result.ToMeasureUnitGroupDataList();
        // Console.WriteLine($"数据长度:{data.Count}");
        
        // // 公司
        // var result = await client.exportDataAsync("16FD9F90", 1, 10);
        // var data = result.ToEasCompanyDataList();
        // Console.WriteLine($"数据长度:{data.Count}");
        
        // // 仓库
        // var result = await client.exportDataAsync("BBE9F8AE", 1, 10);
        // var data = result.ToEasWarehouseDataList();
        // Console.WriteLine($"数据长度:{data.Count}");
        
        // // 库位
        // var result = await client.exportDataAsync("205FF86A", 1, 1000);
        // var data = result.ToEasLocationDataList();
        // Console.WriteLine($"数据长度:{data.Count}");
        
        // // 库存
        // var result = await client.exportDataAsync("BA8AD747", 1, 1000);
        // var data = result.ToEasInventoryDataList();
        // Console.WriteLine($"数据长度:{data.Count}");
        
        // // 通用
        // var result = await client.exportDataAsync("BA8AD747", 1, 10);
        // Console.WriteLine($"数据长度:{result.exportDataReturn.Length}");
    }

    [TestMethod]
    public async Task EasDataProvider()
    {
        var scope = _serviceProvider.CreateScope();
        var provider = scope.ServiceProvider.GetRequiredService<IThirdPartyDataProvider>();
        var data = await provider.GetMaterial();
        Console.WriteLine($"数据长度:{data.Length}");
    }
    
    [TestMethod]
    public async Task DataSync()
    {
        var scope = _serviceProvider.CreateScope();
        var provider = scope.ServiceProvider.GetRequiredService<DataSyncService>();
        var data = await provider.CleanMaterial();
        Console.WriteLine($"数据长度:{data.Count}");
    }
}